﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;

namespace SurfAnalizer
{
    class Program
    {
        static Regex _ageRegex = new Regex(@"Age:(?<Age>\d*)", RegexOptions.IgnoreCase | RegexOptions.Compiled);
        static Regex _ageHistory= new Regex(@"({ (?<framekey>\d+), \((?<x>\d+),(?<y>\d+)\)})", RegexOptions.IgnoreCase | RegexOptions.Compiled);

        static void CalculateDistribution(StreamReader reader)
        {
            var disr = new Dictionary<int, int>();
            int count = 0;
            while (!reader.EndOfStream)
            {
                var ageString = reader.ReadLine();
                var historyString = reader.ReadLine();
                reader.ReadLine();

                var age = int.Parse(_ageRegex.Match(ageString).Groups["Age"].Value);
                if (disr.ContainsKey(age))
                    disr[age]++;
                else
                    disr.Add(age, 1);
                count++;
            }

            Console.WriteLine("Ages distribution (overall: {0})", count);
            foreach (KeyValuePair<int, int> pair in disr)
            {
                Console.WriteLine("{0}\t{1}", pair.Key, pair.Value);
            }
        }

        static void RemoveWeakFeatures(StreamReader reader, StreamWriter writer, int thresholdAge)
        {
            int count = 0;
            while (!reader.EndOfStream)
            {
                var ageString = reader.ReadLine();
                var historyString = reader.ReadLine();
                reader.ReadLine();

                var age = int.Parse(_ageRegex.Match(ageString).Groups["Age"].Value);
                if (age >= thresholdAge)
                {
                    writer.WriteLine(ageString);
                    writer.WriteLine(historyString);
                    writer.WriteLine();
                }
            }
        }

        static readonly Dictionary<int, Frame> Frames = new Dictionary<int, Frame>(350);

        static public void AgreegateByFrames(StreamReader reader)
        {
            int count = 0;
            while (!reader.EndOfStream)
            {
                var ageString = reader.ReadLine();
                var historyString = reader.ReadLine();
                reader.ReadLine();

                var age = int.Parse(_ageRegex.Match(ageString).Groups["Age"].Value);

                var feature = new Feature {Age = age};

                var matches = _ageHistory.Matches(historyString);

                foreach (Match m in matches)
                {
                    var key = int.Parse(m.Groups["framekey"].Value);
                    var x = int.Parse(m.Groups["x"].Value);
                    var y = int.Parse(m.Groups["y"].Value);

                    feature.HistoryPoints.Add(new Point(x,y));

                    if (Frames.ContainsKey(key))
                    {
                        var f = Frames[key];
                        f.Features.Add(feature);
                        feature.OnFrames.Add(f);
                    }
                    else
                    {
                        var frame = new Frame {Key = key, Features = {feature}};
                        Frames.Add(key, frame);

                        feature.OnFrames.Add(frame);
                    }
                }
                count++;
            }
            
            foreach (var f in Frames)
                Console.WriteLine("Frame[{0}].Features.Count = {1}", f.Key, f.Value.Features.Count);
            Console.WriteLine("OvelAll features.Count = " + count);

            var ids = Frames.Keys.ToList();
            ids.Sort();

            Console.Write("Frames without features: ");
            for (int i = 0; i < ids.Count - 1; i++)
            {
                if (ids[i] + 1 != ids[i + 1])
                    Console.Write(ids[i] + ", ");
            }
            Console.WriteLine();
        }

        static void ShowRelations()
        {
            foreach (var frame in Frames.Values)
            {
                var d = new Dictionary<int, int>();

                foreach (var feature in frame.Features)
                {
                    foreach (var onFrame in feature.OnFrames)
                    {
                        if (d.ContainsKey(onFrame.Key))
                            d[onFrame.Key]++;
                        else
                            d.Add(onFrame.Key, 1);
                    }
                }

                Console.Write("Frame[{0}] related with: ", frame.Key);
                foreach (var i in d)
                    Console.Write("{0}[{1}] ", i.Key, i.Value);

                Console.WriteLine();
                Console.WriteLine();
                var b = Console.ReadKey();
                if (b.Key == ConsoleKey.Escape)
                    return;
            }
        }

        static void Main(string[] args)
        {
            var dir = "..\\..\\..\\output\\";
            var cleanHistory = dir + "history-clean.log";
            var history = dir + "history.log";

//            using (var file = File.OpenText(history))
//            {
                // Step #1:
//                CalculateDistribution(file);
//
                // Step #2:
//                file.BaseStream.Position = 0;
//                using (var writer = new StreamWriter(cleanHistory, false, Encoding.UTF8))
//                {
//                    RemoveWeakFeatures(file, writer, 4);
//                }
//            }

//             Step #3:
            using (var reader = File.OpenText(cleanHistory))
            {
                AgreegateByFrames(reader);
            }

            // Info:
            ShowRelations();

            //Step #4:
            //CreatenewImages(dir);
        }

        private static void CreatenewImages(string root)
        {
            var ids = Frames.Keys.ToList();
            ids.Sort();

            var files = Directory.GetFiles(root, "*.png");

            if (files.Length != ids.Count - 1)
            {
                Console.WriteLine("count of frames don't mustch with *.png files count");
                return;
            }

            var pen = new Pen(Color.Red);

            for (int i = 0; i < files.Length; i++)
            {
                var img = Image.FromFile(files[i]);
                var img2 = new Bitmap(img.Width*2, img.Height);
                var currentFrame = Frames[ids[i + 1]];
                
                var g = Graphics.FromImage(img2);
                g.DrawImage(img, 0,0);
                g.DrawImage(img, img.Width ,0);

                foreach (var feature in currentFrame.Features)
                {
                    var index = feature.OnFrames.FindIndex(f => f.Key == currentFrame.Key);
                    var p = feature.HistoryPoints[index];
                    g.DrawEllipse(pen, img.Width + p.X - 5, p.Y - 5, 10, 10);
                }

                var path = Path.Combine(root, "_" + Path.GetFileNameWithoutExtension(files[i]) + ".png");
                img2.Save(path, ImageFormat.Png);
            }
        }
    }
}


